package it.antonio.ilpizze.assertion.concrete;

import it.antonio.ilpizze.assertion.Assertion;
import it.antonio.ilpizze.assertion.Condition;

public class ArrayAssertion<T> extends Assertion<T[]> {

	public ArrayAssertion(T[] instance) {
		super(instance);
		description("Array");
	}
	
	@Override
	public ArrayAssertion<T> as(String description) {
		description(description);
		return this;
	}

	@Override
	public ArrayAssertion<T> doesNotSatisfy(Condition condition) {
		assertNotSatisfy(condition);
		return this;
	}

	@Override
	public ArrayAssertion<T> isEqualTo(T[] expected) {
		assertEqual(expected);
		return null;
	}

	@Override
	public ArrayAssertion<T> isNotEqualTo(T[] other) {
		assertNotEqual(other);
		return null;
	}

	@Override
	public ArrayAssertion<T> isNotNull() {
		assertNotNull();
		return null;
	}

	@Override
	public ArrayAssertion<T> isNotSameAs(T[] other) {
		assertIsNotSameAs(other);
		return null;
	}

	@Override
	public ArrayAssertion<T> isSameAs(T[] expected) {
		assertIsSameAs(expected);
		return null;
	}

	@Override
	public ArrayAssertion<T> satisfies(Condition condition) {
		assertSatisfy(condition);
		return null;
	}

	public ArrayAssertion<T> hasLength(int length) {
		if (instance.length == length)
			return this;
		fail("the length is not " + length);
		return this;
	}

	public ArrayAssertion<T> contains(Object... args) {
		for (Object o : args) {
			boolean contains = false;
			for(T i: instance){
				if(i != null && i.equals(o)) contains = true;
			}
			if(!contains) fail("contains the one of the objects you passed");
		}
		return this;
	}
	public ArrayAssertion<T> equalElements(T... args) {
		Object[] iArray = args;
		
		// same length
		if(iArray.length != args.length) fail("different elements");
		
		for (int i = 0; i < args.length; i++) {
			if(iArray[i] == null && args[i] == null) continue;
			if (!iArray[i].equals(args[i])) {
				fail("different elements");
			}
		}
		return this;
	}
	public ArrayAssertion<T> isEmpty() {
		if (instance.length == 0)
			return this;
		fail("is not empty");
		return this;
	}

	public ArrayAssertion<T> isNotEmpty() {
		if (instance.length != 0)
			return this;
		fail("is empty");
		return this;
	}

}
